From f84d58cea37477baa736e10775dc60b13dc2baf6 Mon Sep 17 00:00:00 2001 From: Rob Browning Date: Sun, 24 Feb 2008 21:54:51 -0800 Subject: [PATCH] Fix a stack overflow in format (CVE-2007-6109). --- debian/changelog | 10 +- .../fix-format-overflow-cve-2007-6109.diff | 91 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 debian/patches/fix-format-overflow-cve-2007-6109.diff diff --git a/debian/changelog b/debian/changelog index 1f080571815..b6a1700b159 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,7 +8,15 @@ emacs22 (22.1+1-3) unstable; urgency=low * Support has been added for GNU/kFreeBSD. Thanks to Petr Salinger (closes: #451178) - -- Rob Browning Sun, 24 Feb 2008 21:45:59 -0800 + * Incorporate a patch to fix a a stack-based buffer overflow in the + format function which can occur when dealing with high precision + values. The overflow could lead to arbitrary code execution + (CVE-2007-6109). Thanks to Nico Golde for the + 22.1+1-2.2 and 22.1+1-2.3 NMUs. The patch fixes both the CVE + (#455432) and a bug introduced by an incomplete initial patch + (#456235). + + -- Rob Browning Sun, 24 Feb 2008 21:52:24 -0800 emacs22 (22.1+1-2) unstable; urgency=low diff --git a/debian/patches/fix-format-overflow-cve-2007-6109.diff b/debian/patches/fix-format-overflow-cve-2007-6109.diff new file mode 100644 index 00000000000..2893e8a66cd --- /dev/null +++ b/debian/patches/fix-format-overflow-cve-2007-6109.diff @@ -0,0 +1,91 @@ +* A stack overflow in the format function has been fixed. + Patch: fix-format-overflow-cve-2007-6109.diff + Provided-by: Nico Golde + Date: Mon, 10 Dec 2007 02:54:44 +0100 + Added-by: Rob Browning + Status: incorporated upstream + + A stack-based buffer overflow in the format function has been fixed, + one that could lead to arbitrary code execution. The overflow could + happen when dealing with high precision values (CVE-2007-6109). + +Index: sid/src/editfns.c +=================================================================== +--- sid.orig/src/editfns.c ++++ sid/src/editfns.c +@@ -3543,8 +3543,10 @@ + precision[n+1] = 10 * precision[n+1] + *format - '0'; + } + +- if (format - this_format_start + 1 > longest_format) +- longest_format = format - this_format_start + 1; ++ /* Extra +1 for 'l' that we may need to insert into the ++ format. */ ++ if (format - this_format_start + 2 > longest_format) ++ longest_format = format - this_format_start + 2; + + if (format == end) + error ("Format string ends in middle of format specifier"); +@@ -3605,7 +3607,7 @@ + && *format != 'i' && *format != 'X' && *format != 'c') + error ("Invalid format operation %%%c", *format); + +- thissize = 30; ++ thissize = 30 + (precision[n] > 0 ? precision[n] : 0); + if (*format == 'c') + { + if (! SINGLE_BYTE_CHAR_P (XINT (args[n])) +@@ -3803,23 +3805,39 @@ + format - this_format_start); + this_format[format - this_format_start] = 0; + +- if (INTEGERP (args[n])) ++ if (format[-1] == 'e' || format[-1] == 'f' || format[-1] == 'g') ++ sprintf (p, this_format, XFLOAT_DATA (args[n])); ++ else + { +- if (format[-1] == 'd') +- sprintf (p, this_format, XINT (args[n])); +- /* Don't sign-extend for octal or hex printing. */ ++ if (sizeof (EMACS_INT) > sizeof (int) && format[-1] != 'c') ++ { ++ /* Insert 'l' before format spec. */ ++ this_format[format - this_format_start] ++ = this_format[format - this_format_start - 1]; ++ this_format[format - this_format_start - 1] = 'l'; ++ this_format[format - this_format_start + 1] = 0; ++ } ++ ++ if (INTEGERP (args[n])) ++ { ++ if (format[-1] == 'c') ++ sprintf (p, this_format, (int) XINT (args[n])); ++ else if (format[-1] == 'd') ++ sprintf (p, this_format, XINT (args[n])); ++ /* Don't sign-extend for octal or hex printing. */ ++ else ++ sprintf (p, this_format, XUINT (args[n])); ++ } ++ else if (format[-1] == 'c') ++ sprintf (p, this_format, (int) XFLOAT_DATA (args[n])); ++ else if (format[-1] == 'd') ++ /* Maybe we should use "%1.0f" instead so it also works ++ for values larger than MAXINT. */ ++ sprintf (p, this_format, (EMACS_INT) XFLOAT_DATA (args[n])); + else +- sprintf (p, this_format, XUINT (args[n])); ++ /* Don't sign-extend for octal or hex printing. */ ++ sprintf (p, this_format, (EMACS_UINT) XFLOAT_DATA (args[n])); + } +- else if (format[-1] == 'e' || format[-1] == 'f' || format[-1] == 'g') +- sprintf (p, this_format, XFLOAT_DATA (args[n])); +- else if (format[-1] == 'd') +- /* Maybe we should use "%1.0f" instead so it also works +- for values larger than MAXINT. */ +- sprintf (p, this_format, (EMACS_INT) XFLOAT_DATA (args[n])); +- else +- /* Don't sign-extend for octal or hex printing. */ +- sprintf (p, this_format, (EMACS_UINT) XFLOAT_DATA (args[n])); + + if (p > buf + && multibyte diff --git a/debian/patches/series b/debian/patches/series index 782493ca4c5..f7397b26a27 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -12,4 +12,5 @@ require-movemail-use-liblockfile.diff avoid-fakemail-mail-loss.diff version-mention-debian.diff support-gnu-kfreebsd.diff +fix-format-overflow-cve-2007-6109.diff autofiles.diff -- 2.30.2